<html>

<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
<title>Monitor e Rendezvous</title>
<link href="styleMain.css" rel="stylesheet" type="text/css">
</head>

<body>
<p class="titulo">Exemplos para Monitor e Rendezvous</p>
<p class="secao">Monitor</p> 
<p>Exemplos de uso de Monitores em LI2:</p>

<ul>
  <li>Exemplo 1: Esse exemplo cria dois processos paralelos que realizam tarefas 
    distintas. Para compreender o uso do mecanismo, deve-se atentar a execu&ccedil;&atilde;o 
    do procedimento incA e a chamada do notify() dentro do bloco sincronizado, 
    que &eacute; onde ocorre a sincroniza&ccedil;&atilde;o da execu&ccedil;&atilde;o 
    dos dois processos paralelos.<br><br>
    Caso o procedimento incA execute primeiro, a vari&aacute;vel compartilhada 
    &quot;a&quot; ser&aacute; sincronizada (bloqueada para aquele processo). O 
    procedimento vai incrementar &quot;a&quot;, vai escrever &quot;parou&quot; 
    e vai &quot;dormir&quot;, cedendo ent&atilde;o a vez a quem quiser utilizar 
    &quot;a&quot;. Desta forma, o segundo processo poder&aacute; somar 2 &agrave; 
    vari&aacute;vel &quot;a&quot; e ent&atilde;o &quot;acordar&quot; o primeiro 
    processo para que ele continue e escreva &quot;continuou&quot; e depois incremente 
    &quot;a&quot;.<br><br>
    Caso o segundo processo execute primeiro, a vari&aacute;vel &quot;a&quot; 
    ser&aacute; somada a 2 e s&oacute; depois que o primeiro processo poder&aacute; 
    incrementar &quot;a&quot;. Neste caso temos um problema, pois o procedimento 
    incA vai ficar parado para sempre quando chamar o wait(), pois n&atilde;o 
    ter&aacute; ningu&eacute;m para chamar acord&aacute;-lo usando o notify().<br>
  </li>
</ul>
<table width="300" border="0" align="center">
  <tr> 
    <td>
<pre>
{
    <span class="palavrasReservadas">var</span> a = 0, 
    <span class="palavrasReservadas">proc</span> incA ()  {
        <span class="palavrasReservadas">synch</span>( a ) {
            a := a + 1;
            <span class="palavrasReservadas">write</span>("parou");
            <span class="palavrasReservadas">wait</span>( a );
            <span class="palavrasReservadas">write</span>("continuou");
            a := a + 1
        }
    };

    <span class="palavrasReservadas">call</span> incA()
    <span class="palavrasReservadas">par</span>
    <span class="palavrasReservadas">synch</span>( a ) {
        a := a + 2;
        <span class="palavrasReservadas">notify</span>( a )
    }
}
</pre>
	</td>
  </tr>
</table>
<ul>
  <li>Exemplo 2: Este exemplo mostra uma aplica&ccedil;&atilde;o de Monitor em 
    que n&atilde;o &eacute; poss&iacute;vel determinar o resultado de antem&atilde;o, 
    isso porque se a primeira linha de execu&ccedil;&atilde;o conseguir a trava 
    antes da segunda linha, o resultado final ser&aacute; 2. Se, ao inv&eacute;s 
    disso, a segunda linha de execu&ccedil;&atilde;o conseguir a trava sobre A 
    antes da primeira, o resultado ser&aacute; 1. Esse &eacute; um bom exemplo 
    onde a aplica&ccedil;&atilde;o de Rendezvous &eacute; mais indicada por apresentar 
    um comportamento determin&iacute;stico.</li>
</ul>
<table width="300" border="0" align="center">
  <tr> 
    <td>
<pre>
{ 
    <span class="palavrasReservadas">var</span> a  =  0, 
    <span class="palavrasReservadas">proc</span> incA () {
        <span class="palavrasReservadas">synch</span>( a ) {
            a := a + 1
        };
        <span class="palavrasReservadas">write</span>( a );
        <span class="palavrasReservadas">write</span>(" ")
    },
    <span class="palavrasReservadas">proc</span> incB () {
        <span class="palavrasReservadas">synch</span>( a ) {
            a := a + a
        };
        <span class="palavrasReservadas">write</span>( a );
        <span class="palavrasReservadas">write</span>(" ")
    };

    <span class="palavrasReservadas">call</span> incA()
    par
    <span class="palavrasReservadas">call</span> incB()
}
</pre>
    </td>
  </tr>
</table>
<p class="secao">Rendezvous</p>
<p>Exemplos do uso de Rendezvous:</p>
<ul>
  <li>Exemplo 1: Cria dois processos paralelos que escrevem suas variaveis locais 
    no console. As duas est&atilde;o em paralelo, mas a execu&ccedil;&atilde;o 
    &eacute; determin&iacute;stica devido ao em paralelo e compartilham um recurso 
    global: a vari&aacute;vel 'x'.</li>
</ul>
<table width="300" border="0" align="center">
  <tr valign="top"> 
    <td>
<pre>
{
    <span class="palavrasReservadas">entry</span> sync() {
        <span class="palavrasReservadas">skip</span>
    };

    {
        <span class="palavrasReservadas">var</span> y = 5;
        {
            <span class="palavrasReservadas">accept</span> sync;
            <span class="palavrasReservadas">write</span>(y);
        }
    }
    <span class="palavrasReservadas">par</span>
    {
        <span class="palavrasReservadas">var</span> x = 0;
        {
            <span class="palavrasReservadas">write</span>(x);
            <span class="palavrasReservadas">callEntry</span> sync();
        }
    }    
}</pre>
	</td>
    <td>
<pre>

// Declaracao das variaveis globais
// (nao faz nada)
// ...
// .
// Bloco da primeira task
// Declaracao de suas variaveis locais
// ...
// Ponto de sincronizacao
// ...
// ...
// .
// Task1 paralela a Task2
// ...
// .
// .
// Escreve o x
// Se reune com a Task1
// .
// Fim da Task2
// Fim do Programa
</pre>
</td>
  </tr>
</table>
<ul>
  <li>Exemplo 2: Este exemplo mostra uma t&iacute;pica aplica&ccedil;&atilde;o 
    de Rendezvous: o produtor-consumidor. <br>
    Observe que s&atilde;o criadas duas tasks que utilizam uma variavel global 
    (<em>dobro</em>). A segunda task entra com o valor inicial na vari&aacute;vel 
    <em>dobro</em> e invoca a primeira para fazer o processamento, em seguida 
    ela consome o resultado, imprimindo no console o valor posterior de <em>dobro</em>.<br>
    Esse &eacute; um exemplo em que a seq&uuml;&ecirc;ncia do acesso a esse recurso 
    compartilhado tem que ser perfeitamente sincronizado. Experimente n&atilde;o 
    usar os operadores de Rendezvous nesse exemplo e vejam como o resultado &eacute; 
    inesperado.</li>
</ul>
<table width="300" border="0" align="center">
  <tr>
    <td>
<pre>
{
    <span class="palavrasReservadas">var</span> dobro = 0,
    
    <span class="palavrasReservadas">entry</span> produza()
    {
        dobro := dobro + dobro
    };

    {
        <span class="palavrasReservadas">var</span> i = 0;
        {
            <span class="palavrasReservadas">while</span> ( <span class="palavrasReservadas">not</span> i == 11 ) <span class="palavrasReservadas">do</span>
            {
                <span class="palavrasReservadas">accept</span> produza;
                i := i + 1;
            };
        }
    }
    <span class="palavrasReservadas">par</span>
    {
        <span class="palavrasReservadas">var</span> i = 0;
        {
            <span class="palavrasReservadas">while</span> ( <span class="palavrasReservadas">not</span> i == 11 ) <span class="palavrasReservadas">do</span>
            {
                dobro := i;
                <span class="palavrasReservadas">write</span>("Dobro de "); <span class="palavrasReservadas">write</span>(i); <span class="palavrasReservadas">write</span>(": ");
                <span class="palavrasReservadas">callEntry</span> produza();
                <span class="palavrasReservadas">write</span>(dobro); <span class="palavrasReservadas">write</span>(" || ");
                i := i + 1;
            };
        }
    }
}
</pre>
	</td>
  </tr>
</table>
<p>&nbsp;</p>
<ul>
  <li>Exemplo 3: Rendezvous &eacute; um mecanismo muito flex&iacute;vel e utilizado 
    para diversas solu&ccedil;&otilde;es em programa&ccedil;&atilde;o concorrente. 
    Abaixo est&aacute; um exemplo em que o Rendezvous &eacute; utilizado como 
    escalonador de tarefas. Ele define a seq&uuml;&ecirc;ncia em que as tarefas 
    v&atilde;o executar, quando na aus&ecirc;ncia de um escalonador no sistema 
    operacional que possa ser modificado.<br>
    <br>
    Neste exemplo s&atilde;o definidos tr&ecirc;s processos concorrentes que imprimem 
    algo no console. Essa impress&atilde;o &eacute; sempre ordenada e determin&iacute;stica 
    devido aos operadores de Rendezvous.<br>
    <br>
    ATEN&Ccedil;&Atilde;O: estas tasks est&atilde;o em loop infinito, portanto 
    o programa n&atilde;o vai parar.</li>
</ul>
<table width="300" border="0" align="center">
  <tr>
    <td>
<pre>
{
    <span class="palavrasReservadas">var</span> i = 1,

    <span class="palavrasReservadas">entry</span> sync1() {
        <span class="palavrasReservadas">skip</span>
    },

    <span class="palavrasReservadas">entry</span> sync2() {
        <span class="palavrasReservadas">skip</span>
    },

    <span class="palavrasReservadas">entry</span> sync3() {
        <span class="palavrasReservadas">skip</span>
    };

    {
        <span class="palavrasReservadas">var</span> y = 5;
        {
            <span class="palavrasReservadas">while</span> ( <span class="palavrasReservadas">not</span> i == 0 ) <span class="palavrasReservadas">do</span>
            {
                <span class="palavrasReservadas">accept</span> sync1;
                <span class="palavrasReservadas">write</span>("task2");
                <span class="palavrasReservadas">callEntry</span> sync3();
            };
        }
    }
    <span class="palavrasReservadas">par</span>
    {
        <span class="palavrasReservadas">var</span> x = 0;
        {
            <span class="palavrasReservadas">while</span> ( <span class="palavrasReservadas">not</span> i == 0 ) <span class="palavrasReservadas">do</span>
            {
                <span class="palavrasReservadas">accept</span> sync2;
                <span class="palavrasReservadas">write</span>("task1|");
                <span class="palavrasReservadas">callEntry</span> sync1();
            };
        }
    }
    <span class="palavrasReservadas">par</span>
    {
        <span class="palavrasReservadas">while</span> ( <span class="palavrasReservadas">not</span> i == 0 ) <span class="palavrasReservadas">do</span>
        {
            <span class="palavrasReservadas">write</span>("i: ");
            <span class="palavrasReservadas">write</span>(i);
            <span class="palavrasReservadas">write</span>("-");
            <span class="palavrasReservadas">callEntry</span> sync2();
            i := i + 1;
            <span class="palavrasReservadas">accept</span> sync3;
            <span class="palavrasReservadas">write</span>(" || ");
        };
    }
}
</pre>
	</td>
  </tr>
</table>
<p>Observe o mesmo exemplo acima SEM o uso de Rendezvous e perceba que a seq&uuml;&ecirc;ncia 
  das tarefas que s&atilde;o executadas &eacute; completamente aleat&oacute;ria.</p>
<table width="300" border="0" align="center">
  <tr>
    <td>
<pre>
{
    var i = 1;

    {
        var y = 5;
        {
            while ( not i == 0 ) do
            {
                write("task2");
            };
        }
    }
    par
    {
        var x = 0;
        {
            while ( not i == 0 ) do
            {
                write("task1|");
            };
        }
    }
    par
    {
        while ( not i == 0 ) do
        {
            write("i: ");
            write(i);
            write("-");
            i := i + 1;
            write(" || ");
        };
    }
}
</pre>
	</td>
  </tr>
</table>
<div align="center"><strong>Exemplo 3 SEM Rendezvous </strong></div>
<p>&nbsp;</p>
<p class="secao">Escopo Negativo</p>
<p>Os exemplos listados abaixo n&atilde;o deveriam funcionar. Para cada um, existe 
  uma justificativa e explica&ccedil;&atilde;o.</p>
<ul>
  <li>Exemplo 1: Esse c&oacute;digo a seguir mostra um exemplo de deadlock n&atilde;o-determin&iacute;stico. 
    Caso a execu&ccedil;&atilde;o das tasks seja 'C', 'B' e 'A', o programa trava.</li>
  <pre>
{
    <span class="palavrasReservadas">var</span> a = 0, 
    <span class="palavrasReservadas">proc</span> prcA () {
        <span class="palavrasReservadas">synch</span>(a) {
            a := a + 2;
            <span class="palavrasReservadas">write</span>(" vai parar ");
            <span class="palavrasReservadas">wait</span>( a );
            <span class="palavrasReservadas">write</span>(" continuou 1 ")
        }
    },
    <span class="palavrasReservadas">proc</span> prcB () {
        <span class="palavrasReservadas">synch</span>(a) {
            a := a + 1;
            <span class="palavrasReservadas">write</span>(" vai parar ");
            <span class="palavrasReservadas">write</span>( a );
            <span class="palavrasReservadas">write</span>(" continuou 2 ")
        }
    },
    <span class="palavrasReservadas">proc</span> prcC () {
        <span class="palavrasReservadas">synch</span>( a ) {
            a:=a+1;
            <span class="palavrasReservadas">write</span>(" vai acordar ");
            <span class="palavrasReservadas">notify</span>(a)
        }
   };

    <span class="palavrasReservadas">call</span> prcA()
    <span class="palavrasReservadas">par</span>
    <span class="palavrasReservadas">call</span> prcB()
    <span class="palavrasReservadas">par</span>
    <span class="palavrasReservadas">call</span> prcC()
}
  </pre>
  <li>Exemplo 2: No c&oacute;digo abaixo, n&atilde;o h&aacute; chamada ao entry 
    point 'inc'. O comando write(z) n&atilde;o deve ser executado porque espera 
    por uma sincroniza&ccedil;&atilde;o de uma outra tarefa que nunca ocorre, 
    j&aacute; que n&atilde;o existe uma chamada ao inc (callEntry inc(z) ou algo 
    do tipo), somente sua declara&ccedil;&atilde;o.</li>
  <pre>
{
    <span class="palavrasReservadas">var</span> x = 0,
    <span class="palavrasReservadas">var</span> z = 5,
    <span class="palavrasReservadas">entry</span> inc(int y) {
       <span class="palavrasReservadas">write</span>(y)
    };

    {
        <span class="palavrasReservadas">write</span>(x);
        <span class="palavrasReservadas">accept</span> inc;
        <span class="palavrasReservadas">write</span>(z);
    }
}
</pre>
</ul>
</BODY>
</HTML>